<template>
	<div class="gantt-chart" :class="[`is-scroll-${scrollStatus}`]" :style="tableStyle" @scroll="onScroll">
		<div class="thead">
			<div class="th-fixed-left" :style="{ width: `${leftWidth}px` }">
				<el-input placeholder="搜素名称"></el-input>
				<div class="resize-line" ref="lineRef" @mousedown="onmousedown"></div>
			</div>
			<div class="head-time">
				<div class="year">
					<div>《 {{ timeLabel.num }}{{ timeLabel.name }}</div>
					<div>{{ timeLabel.num }}{{ timeLabel.name }} 》</div>
				</div>
				<div class="mounth">
					<div v-for="num in gridNum" :key="num" class="m-item">{{ num }}{{ timeLabel.itemName }}</div>
				</div>
			</div>
		</div>
		<div ref="tbody" class="tbody">
			<template v-for="(row, index) in dataList" :key="index">
				<div v-show="showNode(row)" class="item-row" :class="{ flicker: flickerId === row.id }">
					<div class="td-fixed-left" @click="collapse(row)">
						<div class="left-item" :style="{ paddingLeft: `${((row.level - 1) * 32) + 16}px` }">
							<span>{{ row.name }}</span>
							<el-tag>标签</el-tag>
						</div>
					</div>
					<div class="mounth">
						<div class="item-box">
							<div class="m-item" v-for="num in gridNum" :key="num"></div>
						</div>
						<template v-if="row.showBar">
							<div class="bar" v-for="(item, index) in row.countList" :key="index" :style="barStyle(item)"
								@dblclick="onDblclick(item, row)" @mousemove="onMousemove"></div>
						</template>
					</div>
				</div>
			</template>
		</div>
		<div class="tfooter">footer</div>
	</div>
</template>

<script setup>
import { BAR_COLOR, TIME_TYPE } from './constant'
import { getDaysInMonth } from './utils'
import { ref, nextTick, onMounted, computed, watch } from 'vue'

const emits = defineEmits(['dblclick'])
const props = defineProps({
	height: {
		type: [String, Number],
		default: 500,
	},
	formData: {
		type: Object,
		default: () => { },
	},
	timeType: {
		type: String,
		default: TIME_TYPE.YEAR
	},
	year: {
		type: [String, Number],
		default: ''
	},
	month: {
		type: [String, Number],
		default: ''
	}
})

const tbody = ref(null)
const lineRef = ref(null)
const tbodyHeight = ref(100)
const leftWidth = ref(332)
const rowItemWidth = ref(40)
const flickerId = ref('1')
const dataList = ref([
	{
		id: '1',
		name: '节点1',
		parentId: null,
		level: 1,
		open: false,
		showBar: true,
		countList: [
			{
				startDate: 1,
				endDate: 3,
				red: 20,
				green: 80,
				grey: 0,
				lines: 0,
				// overType: 'prev'
			},
			{
				startDate: 5,
				endDate: 8,
				red: 0,
				green: 100,
				grey: 0,
				lines: 0
			},
			// {
			// 	// startDate: 7,
			// 	// endDate: 12,
			// 	// red: 0,
			// 	// green: 0,
			// 	// grey: 70,
			// 	// lines: 30,
			// 	// overType: 'next'
			// }
		]
	},
	{
		id: '1-1',
		name: '节点1-1',
		parentId: '1',
		level: 2,
		isLeaf: false
	},
	{
		id: '1-1-1',
		name: '节点1-1-1',
		parentId: '1-1',
		level: 3,
		isLeaf: true
	},
	{
		id: '1-2',
		name: '节点1-2',
		parentId: '1',
		level: 2
	},
	{
		id: '2',
		name: '节点2',
		parentId: null,
		level: 1
	},
	{
		id: '3',
		name: '节点3',
		parentId: null,
		level: 1
	},
	{
		id: '4',
		name: '节点4',
		parentId: null,
		level: 1
	},
	{
		id: '5',
		name: '节点5',
		parentId: null,
		level: 1
	},
	{
		id: '6',
		name: '节点6',
		parentId: null,
		level: 1
	},
])
const scrollStatus = ref('')
const gridWidth = ref('')//网格宽度
const gridNum = ref(12)

const timeLabel = computed(() => {
	if (props.timeType === TIME_TYPE.MONTH) return {
		name: '月',
		itemName: '日',
		num: props.month
	}
	return {
		name: '年',
		itemName: '月',
		num: props.year
	}

})
const tableStyle = computed(() => {
	return {
		height: filterHeight(props.height),
		'--tbody-height': `${tbodyHeight.value}px`,
		'--grid-width': gridWidth.value,
		'--left-width': `${leftWidth.value}px`
	}
})

// 颜色条样式
const barStyle = (item) => {
	if (!item) return {}
	let borderRadius = '4px'
	let overWidth = 0;
	let overLeft = 8;
	// 超出
	const { overType } = item;
	// 跨上一年/月
	if (overType === 'prev') {
		borderRadius = '0 4px 4px 0'
		overWidth = 2
		overLeft = 0
	}
	// 跨下一年/月
	if (overType === 'next') {
		borderRadius = '4px 0 0 4px'
		overWidth = 2
	}

	const width = `calc(${((item.endDate - item.startDate) + 1)} * ${rowItemWidth.value}px - ${overWidth}px)`;
	const minWidth = `calc(${((item.endDate - item.startDate))} * 40px + 48px - ${overWidth}px)`;
	const left = `calc(${(item.startDate - 1)} * ${rowItemWidth.value}px + ${overLeft}px)`
	const redEnd = item.red;
	const greenEnd = redEnd + item.green;
	const greyEnd = greenEnd + item.grey;
	const colorList = []
	// 红色
	if (item.red) {
		const nextBar = item.green || item.grey || item.lines
		let str = `${BAR_COLOR.RED} 0, ${BAR_COLOR.RED} ${item.red}%`
		//添加白线
		if (nextBar) str += ', #fff 1px'

		colorList.push(str)
	}
	// 绿色
	if (item.green) {
		const prevBar = item.red
		const nextBar = item.grey || item.lines
		let num = `${redEnd}%`
		if (prevBar) num = `calc(${redEnd}% + 1px)`

		let str = `${BAR_COLOR.GREEN} ${num}, ${BAR_COLOR.GREEN} ${greenEnd}%`
		//添加白线
		if (nextBar) str += ', #fff 1px'

		colorList.push(str)
	}
	// 灰色
	if (item.grey) {
		const prevBar = item.red || item.green
		const nextBar = item.lines
		let num = `${greenEnd}%`
		if (prevBar) num = `calc(${greenEnd}% + 1px)`

		let str = `${BAR_COLOR.GREY} ${num}, ${BAR_COLOR.GREY} ${greyEnd}%`
		//添加白线
		if (nextBar) str += ', #fff 1px'

		colorList.push(str)
	}
	if (item.lines) {
		const prevBar = item.red || item.green || item.grey
		let str = `${greyEnd}%`
		if (prevBar) str = `calc(${greyEnd}% + 1px)`
		colorList.push(`transparent ${str}, transparent 100%`)
	}
	const background = `linear-gradient(to right,${colorList.join(',')})`
	return {
		width,
		minWidth,
		left,
		background,
		borderRadius,
		'--scale-lines': `${item.lines}%`
	};
}
// 拖拽
const onmousedown = (e) => {
	let resize3 = lineRef.value
	let startX = e.clientX
	resize3.left = resize3.offsetLeft
	document.onmousemove = function (e) {
		let endX = e.clientX
		let moveLen = resize3.left + (endX - startX)
		if (moveLen < 240) moveLen = 240
		if (moveLen > 480) moveLen = 480
		leftWidth.value = moveLen
	}
	document.onmouseup = function () {
		document.onmousemove = null
		document.onmouseup = null
		resize3.releaseCapture && resize3.releaseCapture()
	}
	resize3.setCapture && resize3.setCapture()
	return false
}
// 双击
const onDblclick = (item, row) => {
	console.log(item, row)
	emits('dblclick', item, row)
}
// 鼠标移动
const onMousemove = (e) => {
	// console.log(e.target.offsetTop)
	// console.log(e.target.offsetLeft)
}
// 收起子节点
const closeChildren = (node) => {
	dataList.value.forEach(item => {
		if (node.id === item.parentId) {
			item.open = false
			if (!item.isLeaf) {
				closeChildren(item)
			}
		}
	})
}
// 展开收起
const collapse = (node) => {
	node.open = !node.open;
	if (!node.open) closeChildren(node)
	nextTick(() => {
		setTbodyHeight()
	})
}

// 节点显示
const showNode = (node) => {
	const parentNode = dataList.value.find(item => item.id === node.parentId)
	if (parentNode) return parentNode?.open;

	return true;
}

// 滚动
const onScroll = (e) => {
	const { scrollLeft, scrollWidth, clientWidth } = e.target;
	const distance = scrollWidth - clientWidth;
	if (scrollLeft === 0) {
		scrollStatus.value = 'left'
	} else if (scrollLeft === distance) {
		scrollStatus.value = 'right'
	} else {
		scrollStatus.value = 'middle'
	}
}

//高度
const filterHeight = (val) => {
	return val.toString().includes("px") ? val : val + "px";
}
// 设置网格线高度
const setTbodyHeight = () => {
	tbodyHeight.value = tbody.value?.offsetHeight || 150;
	nextTick(() => {
		// 获取单元格真实宽度，用于减少后续计算误差
		const rowItem = document.querySelector('.head-time .m-item')
		if (rowItem) {
			const { width } = rowItem.getBoundingClientRect();
			rowItemWidth.value = width - 8;
		}

	})
}
// 设置网格宽度
const setGridWidth = () => {
	gridNum.value = props.timeType === TIME_TYPE.MONTH ? getDaysInMonth(props.year, props.month) : 12;
	gridWidth.value = `calc(100% / ${gridNum.value})`
}
setGridWidth()
onMounted(() => {
	setTbodyHeight()
})
watch(() => props.timeType, () => {
	setGridWidth()
})
</script>
<style lang="less" scoped>
@import "./ganttChart.less";
</style>
